# -*- coding: utf-8 -*-

import logging
import json

import redis
try:
    import cPickle as pickle
except ImportError:
    import pickle

from mpdev.exceptions import BadConfigurationError

logger = logging.getLogger(__name__)

# todo: 与redis常量设置模块集成
Used = 'Used'
RoomBuyer = 'RoomBuyer'
Header = 'Header'
RoomInfoWxid = 'RoomInfoWxid'
RoomInfoName = 'RoomInfoName'
RoomService = 'RoomService'
Signin = 'Signin_{}_{}'


class RedisInterface:
    def __init__(self, app=None):
        self._pool = None
        self.redis = None
        self.app = None
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        try:
            self._pool = redis.BlockingConnectionPool(
                connection_class=redis.Connection,
                host=app.config['REDIS_HOST'],
                port=app.config['REDIS_PORT'],
                password=app.config['REDIS_PASSWORD'],
                db=app.config['REDIS_DB'],
                socket_timeout=app.config['REDIS_SOCKET_TIMEOUT'],
                socket_connect_timeout=app.config['REDIS_SOCKET_CONNECT_TIMEOUT']
            )
        except KeyError:
            raise BadConfigurationError('redis相关配置错误,请检查config.py')
        self.redis = redis.StrictRedis(connection_pool=self._pool)

        self.app = app
        app.redis_interface = self
        app.redis = self.redis

        logger.debug('Redis interface initialized.')

    def get_room_owner(self, room_id):
        # 返回owner的wxid
        logger.debug('Querying redis for room owner. room_id: %s', room_id)
        return self.redis.hget(RoomBuyer, room_id)

    def get_bought_rooms(self, owner_wxid):
        # 返回用户所购买的群
        logger.debug('Querying redis for bought rooms. owner_wxid: %s', owner_wxid)
        return self.redis.hkeys('_'.join((Used, owner_wxid)))

    def room_exists(self, room_id):
        logger.debug('Querying redis for checking room existence. room_id: %s', room_id)
        return self.redis.hexists(RoomBuyer, room_id)

    def get_room_service_robot(self, room_id):
        logger.debug('Querying redis for service robot of room. room_id: %s', room_id)
        return self.redis.hget(RoomService, room_id)

    def get_room_users(self, room_id):
        logger.debug('Querying redis for refreshing users in MySQL. room_id: %s', room_id)
        robot_wxid = self.get_room_service_robot(room_id)
        #users_r = pickle.loads(self.redis.hget('{}_{}'.format(robot_wxid, RoomInfoWxid), room_id))
        users_r = self.redis.hget('{}_{}'.format(robot_wxid, RoomInfoWxid), room_id)
        logger.debug('Retrieved users info from redis: %s', users_r)
        users = {k: {'nickname': v['name']}
                 for k, v in pickle.loads(users_r)['members'].items() if not k.endswith('\x7f')}
        logger.debug('Get user nicknames from redis: %s', users)

        user_headimg_r = self.redis.get('{}_{}'.format(Header, room_id))
        user_headimg = pickle.loads(user_headimg_r)
        logger.debug('Get user headers from redis: %s', user_headimg)
        for wxid, headimg in user_headimg.items():
            if users.get(wxid) is None:
                logger.info(
                    'Missing nickname for %s in redis. Ignore his headimg: %s',
                    wxid,
                    headimg
                )
            else:
                users[wxid]['headimgurl'] = headimg
        users.pop(robot_wxid, None)
        # logger.debug('Fetched room users from redis: %s', users)
        return users

    def get_signin_count(self, room_id, wxid):
        logger.debug(
            'Querying redis for signin count. room_id: %s. wxid: %S',
            room_id,
            wxid
        )
        try:
            res_r = self.redis.get(Signin.format(room_id, wxid))
            if res_r is None:
                return 0
            return json.loads(res_r)['signin_times']
        except:
            logger.warning(
                'Retrieve signin count FAILED'
            )
            return 0

    def get_successive_signin_count(self, room_id, wxid):
        logger.debug(
            'Querying redis for successive signin count. room_id: %s. wxid: %S',
            room_id,
            wxid
        )
        try:
            res_r = self.redis.get(Signin.format(room_id, wxid))
            if res_r is None:
                return 0
            return json.loads(res_r)['consistent']
        except:
            logger.warning(
                'Retrieve successive signin count FAILED'
            )
            return 0